package de.slothsoft.bookmaker.ui;

import java.io.File;
import java.io.IOException;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import de.slothsoft.bookmaker.Downloader;
import de.slothsoft.bookmaker.ProgressMonitor;
import de.slothsoft.bookmaker.parse.WebsiteDescription;
import de.slothsoft.bookmaker.parse.WebsiteDescriptions;

public class BookMakerApplication extends Application {

    private static final Insets INSETS = new Insets(15, 10, 10, 15);

    protected final TextField urlText = new TextField();
    protected final TextField pathText = new TextField();
    protected final Label progressText = new Label();
    protected final ProgressIndicator progressControl = new ProgressIndicator();
    protected final Button downloadButton = new Button("Download");

    private final ProgressMonitor monitor = new ProgressIndicatorMonitor(this.progressText, this.progressControl);

    @Override
    public void start(Stage stage) {
        BorderPane root = new BorderPane();
        Scene scene = new Scene(root);
        stage.setTitle("PDF Book Maker");
        stage.setWidth(450);
        stage.setHeight(500);

        root.setTop(createDownloadControls());
        root.setCenter(createSupportedWebsiteGroup());

        hookListeners();

        stage.setScene(scene);
        stage.show();
    }

    protected Node createDownloadControls() {
        int x = 0, y = 0;
        final GridPane group = new GridPane();
        group.setPadding(INSETS);
        ColumnConstraints column1 = new ColumnConstraints(100);
        ColumnConstraints column2 = new ColumnConstraints(100, 100, Double.MAX_VALUE);
        column2.setHgrow(Priority.ALWAYS);
        group.getColumnConstraints().addAll(column1, column2);
        group.setHgap(10);
        group.setVgap(10);

        GridPane.setHalignment(this.downloadButton, HPos.RIGHT);

        group.add(createTitleLabel("Download"), x, y++);
        group.add(new Label("URL:"), x, y++);
        group.add(new Label("Path:"), x, y++);

        y = 1;
        x++;
        group.add(this.urlText, x, y++);
        group.add(this.pathText, x, y++);
        group.add(createProgressControls(), x, y++);
        group.add(this.downloadButton, x, y++);

        this.pathText.setText(System.getProperty("user.dir"));
        blockGui(false);
        return group;
    }

    private Node createProgressControls() {
        final BorderPane group = new BorderPane();
        group.setCenter(this.progressText);
        group.setRight(this.progressControl);
        return group;
    }

    protected Node createSupportedWebsiteGroup() {
        TableColumn<WebsiteDescription, String> columnDisplayName = new TableColumn<>("Website");
        columnDisplayName.setMinWidth(300);
        columnDisplayName.setCellValueFactory(new PropertyValueFactory<WebsiteDescription, String>("displayName"));

        TableView<WebsiteDescription> table = new TableView<WebsiteDescription>();
        table.setItems(FXCollections.observableArrayList(WebsiteDescriptions.createAll()));
        table.getColumns().add(columnDisplayName);

        final BorderPane group = new BorderPane();
        group.setPadding(INSETS);
        group.setTop(createTitleLabel("Supported Websites"));
        group.setCenter(table);

        return group;
    }

    private void hookListeners() {
        this.downloadButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                performDownload();
            }
        });
    }

    protected void performDownload() {
        blockGui(true);
        new Thread() {
            @Override
            public void run() {
                try {
                    download();
                } catch (final IOException e) {
                    e.printStackTrace();
                    getMonitor().setText(e.getMessage());
                } finally {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            blockGui(false);
                        }
                    });
                }
            };
        }.start();
    }

    protected void download() throws IOException {
        final String url = this.urlText.getText();
        File targetFolder = new File(this.pathText.getText());

        Downloader downloader = new Downloader();
        downloader.setMonitor(this.monitor);
        downloader.download(url, targetFolder);
    }

    protected void blockGui(boolean block) {
        this.downloadButton.setDisable(block);
        this.urlText.setEditable(!block);
        this.pathText.setEditable(!block);
        this.progressControl.setVisible(block);
        if (block) {
            this.monitor.clear();
        }
    }

    protected Node createTitleLabel(String title) {
        final Label label = new Label(title);
        label.setFont(new Font("Arial", 20));
        return label;
    }

    protected ProgressMonitor getMonitor() {
        return this.monitor;
    }

}